package cn.com.bluemoon.daps.standard.service.impl;

import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.common.enums.StandardDataType;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.common.validation.JValidUtils;
import cn.com.bluemoon.daps.standard.entity.DapStandardBasic;
import cn.com.bluemoon.daps.standard.entity.DapStandardBasicDic;
import cn.com.bluemoon.daps.standard.excel.easypoi.BasicStandardVerifyHandler;
import cn.com.bluemoon.daps.standard.mapper.DapStandardBasicDicMapper;
import cn.com.bluemoon.daps.standard.service.DapStandardBasicDicService;
import cn.com.bluemoon.daps.standard.service.DapStandardBasicService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 基础标准-字典代码表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-08-03
 */
@Slf4j
@Service
@Transactional(rollbackFor = {DapException.class, Exception.class})
public class DapStandardBasicDicServiceImpl extends ServiceImpl<DapStandardBasicDicMapper, DapStandardBasicDic>
        implements DapStandardBasicDicService {

    @Resource
    @Lazy
    private DapStandardBasicService standardBasicService;

    /**
     * 检查字典表数据
     * 返回错误信息
     * 本方法用于表单提交的数据校验中
     * 若是导入的相同校验请查看 {@link BasicStandardVerifyHandler} 因为导入中还没建立Id关联关系
     */
    private String checkModelOk(DapStandardBasicDic dapStandardBasicDic, DapStandardBasic standardBasic) {
        if (dapStandardBasicDic != null) {
            // 增加针对来源是导入的，导入已处理，减少每条数据查询
            if (dapStandardBasicDic.getDataSourceFromExcel()) {
                log.info("导入数据，跳过系统录入校验逻辑");
                return null;
            }
            // jira:BDPROAB-1803
            List<Map<String, Object>> duplicates;
            if (StringUtils.isBlank(standardBasic.getStandardUniqueId())) {
                duplicates = getBaseMapper().findDuplicateBaseCodeStandardUniqueIdIsNull(dapStandardBasicDic.getBaseCode(), dapStandardBasicDic.getBaseCodeName(),
                        standardBasic.getId());
            } else {
                duplicates = getBaseMapper().findDuplicateBaseCode(dapStandardBasicDic.getBaseCode(), dapStandardBasicDic.getBaseCodeName(),
                        standardBasic.getId(), standardBasic.getStandardUniqueId());
            }
            if (!duplicates.isEmpty()) {
                return "代码英文名称或中文名称已存在，不可添加";
            }
            DapStandardBasicDic dic = new DapStandardBasicDic();
            dic.setCodeName(dapStandardBasicDic.getCodeName());
            dic.setBasicStandardId(dapStandardBasicDic.getBasicStandardId());
            LambdaQueryWrapper<DapStandardBasicDic> ne = Wrappers.lambdaQuery(dic)
                    .eq(DapStandardBasicDic::getBmStatus, BmStatus.ON)
                    .ne(StringUtils.isNotBlank(dapStandardBasicDic.getId()), DapStandardBasicDic::getId, dapStandardBasicDic.getId());
            List<DapStandardBasicDic> list = list(ne);
            if (!list.isEmpty()) {
                return "基础标准中代码名称已存在,不可添加";
            }
            dic.setCodeName(null);
            dic.setCodeValue(dapStandardBasicDic.getCodeValue());
            ne = Wrappers.lambdaQuery(dic)
                    .eq(DapStandardBasicDic::getBmStatus, BmStatus.ON)
                    .ne(DapStandardBasicDic::getBasicStandardId, dapStandardBasicDic.getBasicStandardId());
            list = list(ne);
            if (!list.isEmpty()) {
                return "基础标准中代码值已存在,代码值,不可添加";
            }
            dic.setCodeName(dapStandardBasicDic.getCodeName());
            ne = Wrappers.lambdaQuery(dic)
                    .eq(DapStandardBasicDic::getBmStatus, BmStatus.ON)
                    .ne(DapStandardBasicDic::getBasicStandardId, dapStandardBasicDic.getBasicStandardId());
            list = list(ne);
            if (!list.isEmpty()) {
                return "基础标准中代码名称和代码值已存在，不可添加";
            }
        }
        return null;
    }

    @Override
    public void deleteByStandardId(String[] standardId, boolean isLogicDel) {
        if (standardId == null || standardId.length == 0) {
            return;
        }
        LambdaQueryWrapper<DapStandardBasicDic> where = Wrappers.lambdaQuery(new DapStandardBasicDic())
                .in(true, DapStandardBasicDic::getBasicStandardId, Arrays.stream(standardId).toArray());
        if (isLogicDel) {
            List<DapStandardBasicDic> list = list(where);
            if (!list.isEmpty()) {
                list.forEach(d -> d.setBmStatus(BmStatus.DELETE));
                updateBatchById(list);
            }
        } else {
            remove(where);
        }
    }

    /**
     * 先删除旧的字典数据 再新增(id会变，但是编码不变，故对外使用应该是编码）
     */
    @Override
    public void mySaveOrUpdateBatch(DapStandardBasic dapStandardBasic,
                                    List<DapStandardBasicDic> basicDics,
                                    String standardId) {
        standardId = Optional.ofNullable(standardId).orElse(dapStandardBasic.getId());
        // 增加判断是否存在标准 进行编辑或者新增
        DapStandardBasic standardBasic = standardBasicService.getById(standardId);
        if (standardBasic != null && !standardBasic.getDataSourceFromExcel()) {
            // 先删除旧的字典数据 再新增(id会变，但是编码不变，故对外使用应该是编码）
            boolean remove = remove(bmLambdaQuery().eq(DapStandardBasicDic::getBasicStandardId, standardId));
            log.info("编辑字典数据，先删除旧的字典数据 再新增(id会变，但是编码不变，故对外使用应该是编码），删除情况：{}", remove);
        }
        boolean needAddDic = checkModelOk(basicDics, standardBasic);
        if (needAddDic) {
            final String finalStandardId = standardId;
            basicDics.forEach(basicDic -> {
                basicDic.setId(null);
                basicDic.setBasicStandardId(finalStandardId);
            });
            saveBatch(basicDics);
        }
    }

    @Override
    public Map<String, String> findDistinceBaseCodeAndName() {
        LambdaQueryWrapper<DapStandardBasicDic> select = bmLambdaQuery()
                .select(DapStandardBasicDic::getBaseCode, DapStandardBasicDic::getBaseCodeName)
                .groupBy(DapStandardBasicDic::getBaseCode);
        List<DapStandardBasicDic> list = list(select);
        final Map<String, String> dbStandardDics = list.parallelStream().filter(Objects::nonNull).collect(Collectors.toMap(DapStandardBasicDic::getBaseCode, DapStandardBasicDic::getBaseCodeName, (a, b) -> b));
        return dbStandardDics;
    }

    private boolean checkModelOk(List<DapStandardBasicDic> basicDics, DapStandardBasic standardBasic) {
        if (standardBasic != null && StandardDataType.代码类.equals(standardBasic.getDataType())) {
            // 针对代码类的必须要有字典
            if (standardBasic.getDataSourceFromExcel()) {
                log.info("导入数据，跳过系统录入校验逻辑");
                return true;
            }
            BmAssetUtils.isTrue(basicDics != null && !basicDics.isEmpty(), "标准数据类型为[代码类]必须有字典代码数据");
            basicDics.stream().peek(d -> {
                d.setBasicStandardId(standardBasic.getId());
                d.setBmStatus(BmStatus.ON);
                JValidUtils valid = JValidUtils.INSTANCE.checkValid(d);
                BmAssetUtils.isTrue(valid.isValid(), "代码类中的字典校验不通过,详情：" + valid.getValidateMsg());
            }).forEach(b -> {
                String errorMsg = checkModelOk(b, standardBasic);
                BmAssetUtils.isNull(errorMsg, errorMsg);
            });
            return true;
        } else {
            if (basicDics != null) {
                basicDics.clear();
            }
            return false;
        }
    }
}
